#include "formmasks.h"
#include "ui_formmasks.h"
#include "kb_map.h"
#include <stdio.h>

const uint8_t FormMasks::cols = 21;
const uint8_t FormMasks::rows = 6;
struct kbRGB_ctrl_t FormMasks::ctrl;
#define  KB_LEFT   0x00
#define  KB_RIGHT  0x01
#define  KB_UP     0x00
#define  KB_DOWN   0x02

void kb_map_update(uint32_t masks[8], uint8_t cols, uint8_t rows, const uint8_t kb_map[6][21])
{
    uint8_t col, row;
    uint32_t mask;
    if(cols>32) cols=32;
    if(rows>6)  rows=6;
    for(row=0; row<rows; row++)
    {
        mask = 0;
        for(col=0; col<cols; col++)
        {
            if(0x00!=kb_map[row][col]) mask |= (0x1<<col);
        }
        masks[row] = mask;
    }
}
void kb_scanning(const uint8_t start, const int Horizontal, const int ZigZag, uint32_t *const reverseX, uint32_t *const reverseY)
{
    uint32_t revX=0;
    uint32_t revY=0;
    if(Horizontal) // 横向扫描
    {
        // OK
        if((KB_LEFT |KB_UP)==(start&0x03))      // 起点在左上
        {
            revX=0x00;
            revY=0x00;
        }
        // OK
        if((KB_LEFT |KB_DOWN)==(start&0x03))      // 起点在左下
        {
            revX=0x00;
            revY=0xFFFFFFFF;
        }
        // OK
        if((KB_RIGHT|KB_UP)==(start&0x03))      // 起点在右上
        {
            revX=0xFFFFFFFF;
            revY=0x00;
        }
        // OK
        if((KB_RIGHT|KB_DOWN)==(start&0x03))      // 起点在右下
        {
            revX=0xFFFFFFFF;
            revY=0xFFFFFFFF;
        }
        if(ZigZag) // 横向之字形
        {
            // OK
            if((KB_LEFT |KB_UP)==(start&0x03))      // 起点在左上
            {
                revX=0xAAAAAAAA;
                revY=0x00;
            }
            // OK
            if((KB_LEFT |KB_DOWN)==(start&0x03))      // 起点在左下
            {
                revX=0xAAAAAAAA;
                revY=0xFFFFFFFF;
            }
            // OK
            if((KB_RIGHT|KB_UP)==(start&0x03))      // 起点在右上
            {
                revX=0x55555555;
                revY=0x00;
            }
            // OK
            if((KB_RIGHT|KB_DOWN)==(start&0x03))      // 起点在右下
            {
                revX=0x55555555;
                revY=0xFFFFFFFF;
            }
        }
    }
    else // 纵向扫描
    {
        // OK
        if((KB_LEFT |KB_UP)==(start&0x03))      // 起点在左上
        {
            revX=0x00;
            revY=0x00;
        }
        // OK
        if((KB_LEFT |KB_DOWN)==(start&0x03))      // 起点在左下
        {
            revX=0x00;
            revY=0xFFFFFFFF;
        }
        // OK
        if((KB_RIGHT|KB_UP)==(start&0x03))      // 起点在右上
        {
            revX=0xFFFFFFFF;
            revY=0x00;
        }
        // OK
        if((KB_RIGHT|KB_DOWN)==(start&0x03))      // 起点在右下
        {
            revX=0xFFFFFFFF;
            revY=0xFFFFFFFF;
        }
        if(ZigZag) // 纵向之字形
        {
            // OK
            if((KB_LEFT |KB_UP)==(start&0x03))      // 起点在左上
            {
                revX=0x00;
                revY=0xAAAAAAAA;
            }
            if((KB_LEFT |KB_DOWN)==(start&0x03))      // 起点在左下
            {
                revX=0x00;
                revY=0x55555555;
            }
            // OK
            if((KB_RIGHT|KB_UP)==(start&0x03))      // 起点在右上
            {
                revX=0xFFFFFFFF;
                revY=0xAAAAAAAA;
            }
            // OK
            if((KB_RIGHT|KB_DOWN)==(start&0x03))      // 起点在右下
            {
                revX=0xFFFFFFFF;
                revY=0x55555555;
            }
        }
    }
    *reverseX = revX;
    *reverseY = revY;
    //qDebug("[%s--%d] reverseX:%08X reverseY:%08X ", __func__, __LINE__, revX, revY);
}

FormMasks::FormMasks(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormMasks),
    timer_masks(this)
{
    ui->setupUi(this);
    checkBoxs[0][0]  = ui->checkBox_A0;
    checkBoxs[0][1]  = ui->checkBox_A1;
    checkBoxs[0][2]  = ui->checkBox_A2;
    checkBoxs[0][3]  = ui->checkBox_A3;
    checkBoxs[0][4]  = ui->checkBox_A4;
    checkBoxs[0][5]  = ui->checkBox_A5;
    checkBoxs[0][6]  = ui->checkBox_A6;
    checkBoxs[0][7]  = ui->checkBox_A7;
    checkBoxs[0][8]  = ui->checkBox_A8;
    checkBoxs[0][9]  = ui->checkBox_A9;
    checkBoxs[0][10] = ui->checkBox_A10;
    checkBoxs[0][11] = ui->checkBox_A11;
    checkBoxs[0][12] = ui->checkBox_A12;
    checkBoxs[0][13] = ui->checkBox_A13;
    checkBoxs[0][14] = ui->checkBox_A14;
    checkBoxs[0][15] = ui->checkBox_A15;
    checkBoxs[0][16] = ui->checkBox_A16;
    checkBoxs[0][17] = ui->checkBox_A17;
    checkBoxs[0][18] = ui->checkBox_A18;
    checkBoxs[0][19] = ui->checkBox_A19;
    checkBoxs[0][20] = ui->checkBox_A20;
    checkBoxs[1][0]  = ui->checkBox_B0;
    checkBoxs[1][1]  = ui->checkBox_B1;
    checkBoxs[1][2]  = ui->checkBox_B2;
    checkBoxs[1][3]  = ui->checkBox_B3;
    checkBoxs[1][4]  = ui->checkBox_B4;
    checkBoxs[1][5]  = ui->checkBox_B5;
    checkBoxs[1][6]  = ui->checkBox_B6;
    checkBoxs[1][7]  = ui->checkBox_B7;
    checkBoxs[1][8]  = ui->checkBox_B8;
    checkBoxs[1][9]  = ui->checkBox_B9;
    checkBoxs[1][10] = ui->checkBox_B10;
    checkBoxs[1][11] = ui->checkBox_B11;
    checkBoxs[1][12] = ui->checkBox_B12;
    checkBoxs[1][13] = ui->checkBox_B13;
    checkBoxs[1][14] = ui->checkBox_B14;
    checkBoxs[1][15] = ui->checkBox_B15;
    checkBoxs[1][16] = ui->checkBox_B16;
    checkBoxs[1][17] = ui->checkBox_B17;
    checkBoxs[1][18] = ui->checkBox_B18;
    checkBoxs[1][19] = ui->checkBox_B19;
    checkBoxs[1][20] = ui->checkBox_B20;
    checkBoxs[2][0]  = ui->checkBox_C0;
    checkBoxs[2][1]  = ui->checkBox_C1;
    checkBoxs[2][2]  = ui->checkBox_C2;
    checkBoxs[2][3]  = ui->checkBox_C3;
    checkBoxs[2][4]  = ui->checkBox_C4;
    checkBoxs[2][5]  = ui->checkBox_C5;
    checkBoxs[2][6]  = ui->checkBox_C6;
    checkBoxs[2][7]  = ui->checkBox_C7;
    checkBoxs[2][8]  = ui->checkBox_C8;
    checkBoxs[2][9]  = ui->checkBox_C9;
    checkBoxs[2][10] = ui->checkBox_C10;
    checkBoxs[2][11] = ui->checkBox_C11;
    checkBoxs[2][12] = ui->checkBox_C12;
    checkBoxs[2][13] = ui->checkBox_C13;
    checkBoxs[2][14] = ui->checkBox_C14;
    checkBoxs[2][15] = ui->checkBox_C15;
    checkBoxs[2][16] = ui->checkBox_C16;
    checkBoxs[2][17] = ui->checkBox_C17;
    checkBoxs[2][18] = ui->checkBox_C18;
    checkBoxs[2][19] = ui->checkBox_C19;
    checkBoxs[2][20] = ui->checkBox_C20;
    checkBoxs[3][0]  = ui->checkBox_D0;
    checkBoxs[3][1]  = ui->checkBox_D1;
    checkBoxs[3][2]  = ui->checkBox_D2;
    checkBoxs[3][3]  = ui->checkBox_D3;
    checkBoxs[3][4]  = ui->checkBox_D4;
    checkBoxs[3][5]  = ui->checkBox_D5;
    checkBoxs[3][6]  = ui->checkBox_D6;
    checkBoxs[3][7]  = ui->checkBox_D7;
    checkBoxs[3][8]  = ui->checkBox_D8;
    checkBoxs[3][9]  = ui->checkBox_D9;
    checkBoxs[3][10] = ui->checkBox_D10;
    checkBoxs[3][11] = ui->checkBox_D11;
    checkBoxs[3][12] = ui->checkBox_D12;
    checkBoxs[3][13] = ui->checkBox_D13;
    checkBoxs[3][14] = ui->checkBox_D14;
    checkBoxs[3][15] = ui->checkBox_D15;
    checkBoxs[3][16] = ui->checkBox_D16;
    checkBoxs[3][17] = ui->checkBox_D17;
    checkBoxs[3][18] = ui->checkBox_D18;
    checkBoxs[3][19] = ui->checkBox_D19;
    checkBoxs[3][20] = ui->checkBox_D20;
    checkBoxs[4][0]  = ui->checkBox_E0;
    checkBoxs[4][1]  = ui->checkBox_E1;
    checkBoxs[4][2]  = ui->checkBox_E2;
    checkBoxs[4][3]  = ui->checkBox_E3;
    checkBoxs[4][4]  = ui->checkBox_E4;
    checkBoxs[4][5]  = ui->checkBox_E5;
    checkBoxs[4][6]  = ui->checkBox_E6;
    checkBoxs[4][7]  = ui->checkBox_E7;
    checkBoxs[4][8]  = ui->checkBox_E8;
    checkBoxs[4][9]  = ui->checkBox_E9;
    checkBoxs[4][10] = ui->checkBox_E10;
    checkBoxs[4][11] = ui->checkBox_E11;
    checkBoxs[4][12] = ui->checkBox_E12;
    checkBoxs[4][13] = ui->checkBox_E13;
    checkBoxs[4][14] = ui->checkBox_E14;
    checkBoxs[4][15] = ui->checkBox_E15;
    checkBoxs[4][16] = ui->checkBox_E16;
    checkBoxs[4][17] = ui->checkBox_E17;
    checkBoxs[4][18] = ui->checkBox_E18;
    checkBoxs[4][19] = ui->checkBox_E19;
    checkBoxs[4][20] = ui->checkBox_E20;
    checkBoxs[5][0]  = ui->checkBox_F0;
    checkBoxs[5][1]  = ui->checkBox_F1;
    checkBoxs[5][2]  = ui->checkBox_F2;
    checkBoxs[5][3]  = ui->checkBox_F3;
    checkBoxs[5][4]  = ui->checkBox_F4;
    checkBoxs[5][5]  = ui->checkBox_F5;
    checkBoxs[5][6]  = ui->checkBox_F6;
    checkBoxs[5][7]  = ui->checkBox_F7;
    checkBoxs[5][8]  = ui->checkBox_F8;
    checkBoxs[5][9]  = ui->checkBox_F9;
    checkBoxs[5][10] = ui->checkBox_F10;
    checkBoxs[5][11] = ui->checkBox_F11;
    checkBoxs[5][12] = ui->checkBox_F12;
    checkBoxs[5][13] = ui->checkBox_F13;
    checkBoxs[5][14] = ui->checkBox_F14;
    checkBoxs[5][15] = ui->checkBox_F15;
    checkBoxs[5][16] = ui->checkBox_F16;
    checkBoxs[5][17] = ui->checkBox_F17;
    checkBoxs[5][18] = ui->checkBox_F18;
    checkBoxs[5][19] = ui->checkBox_F19;
    checkBoxs[5][20] = ui->checkBox_F20;
//    for(uint8_t row_id=0; row_id<rows; row_id++)
//    {
//        for(uint8_t col_id=0; col_id<cols; col_id++)
//        {
//            connect(checkBoxs[row_id][col_id],    SIGNAL(stateChanged(int)), this, SLOT(checkBoxs_Changed(int)));
//        }
//    }
    ui->comboBox_Demo->clear();
    ui->comboBox_Dir->clear();
    //ui->comboBox_End->clear();
    ui->comboBox_Logo->clear();
    ui->comboBox_Start->clear();
    ui->comboBox_Demo->addItem("104键盘");
    ui->comboBox_Demo->addItem("104键盘-Test");
    ui->comboBox_Dir->addItem("横向扫描");
    ui->comboBox_Dir->addItem("纵向扫描");
    ui->comboBox_Dir->addItem("横向之字形");
    ui->comboBox_Dir->addItem("纵向之字形");
//    ui->comboBox_End->addItem("RGB0");
//    ui->comboBox_End->addItem("RGB20");
//    ui->comboBox_End->addItem("RGB105");
//    ui->comboBox_End->addItem("RGB125");
    ui->comboBox_Start->addItem("左上");   // RGB0
    ui->comboBox_Start->addItem("右上");   // RGB20
    ui->comboBox_Start->addItem("左下");   // RGB105
    ui->comboBox_Start->addItem("右下");   // RGB125
    ui->comboBox_Logo->addItem("矩阵之外");
    ui->comboBox_Logo->addItem("不使用");
    for(int cnt=0; cnt<(cols*rows); cnt++)
    {
        ui->comboBox_Logo->addItem("RGB"+QString::number(cnt));
    }
    ui->comboBox_Speed->clear();
    ui->comboBox_Speed->addItem("1");
    ui->comboBox_Speed->addItem("2");
    ui->comboBox_Speed->addItem("3");
    ui->comboBox_Speed->addItem("4");
    ui->comboBox_Speed->addItem("5");
    ui->comboBox_Speed->addItem("6");
    ui->comboBox_Mode->clear();
    for(int i=0; i<40; i++)
    {
        ui->comboBox_Mode->addItem(QString::number(i));
    }
    ui->comboBox_Mode->setCurrentIndex(12);
    ui->comboBox_Demo->setCurrentIndex( 0);
    ui->comboBox_Dir->setCurrentIndex( 0);
    //ui->comboBox_End->setCurrentIndex( 0);
    ui->comboBox_Logo->setCurrentIndex( 0);
    ui->comboBox_Start->setCurrentIndex( 1);
    //memset(ctrl.Masks, 0x00, sizeof(ctrl.Masks));
    memset(&ctrl, 0x00, sizeof(ctrl));
    //QTimer *timer = new QTimer(this);
    connect(&timer_masks, SIGNAL(timeout()), this, SLOT(timer_update()));
    scanning = 0;
    Progress=0;
    KB_Scanning();
    on_comboBox_Logo_currentIndexChanged(0);
    masks_show();
    timer_masks.start(50);

    adjustSize();
}

FormMasks::~FormMasks()
{
//    for(uint8_t row_id=0; row_id<6; row_id++)
//    {
//        for(uint8_t col_id=0; col_id<6; col_id++)
//        {
//            disconnect(checkBoxs[row_id][col_id],    SIGNAL(stateChanged(int)), this, SLOT(checkBoxs_Changed(int)));
//        }
//    }
    disconnect(&timer_masks, SIGNAL(timeout()), this, SLOT(timer_update()));
    delete ui;
}

void FormMasks::timer_update(void)
{
    // 显示键位
    if(false == ui->checkBox_Demo->isChecked()) masks_update();
    // 显示扫描
    else scan_demo(ctrl.reverseX, ctrl.reverseY);
    ctrl.Speed = ui->comboBox_Speed->currentIndex();
    ctrl.IdxMode = ui->comboBox_Mode->currentIndex();
    ctrl.reverse = 0;
    if(ui->checkBox_Rev->isChecked()) ctrl.reverse = 1;
}
void FormMasks::scan_demo(const uint32_t revX, const uint32_t revY)
{
    uint16_t progress = 0;
    int16_t col_id, row_id;
    int32_t x, y;
    uint8_t Scanning[rows][cols];
    static const uint16_t Speed = 30;
    static const uint16_t FPS = 20;
    if(0==scanning)
    {
        scanning=1;
        Progress=0;
    }
    //static double Progress=0;
    Progress += (Speed) / FPS;
    if(Progress>=(cols*rows))
    {
        Progress = 0;
    }
    progress = Progress;
    memset(Scanning, 0x00, sizeof(Scanning));
    for (col_id = 0; col_id < cols; col_id++)
    {
         for (row_id = 0; row_id < rows; row_id++)
        {
             Scanning[row_id][col_id] = 0;
             //if((row_id*cols+col_id)<=progress) Scanning[row_id][col_id] = 1;
             if(ctrl.Horizontal) // 横向扫描
             {
                 if((row_id*cols+col_id)<=progress) Scanning[row_id][col_id] = 1;
             }
             else // 纵向扫描
             {
                 if((row_id+col_id*rows)<=progress) Scanning[row_id][col_id] = 1;
             }
        }
    }
    for(col_id=0; col_id<cols; col_id++)
    {
        for(row_id=0; row_id<rows; row_id++)
        {
            if((revY>>col_id)&0x1) y=rows-1-row_id;
            else y=row_id;
            if((revX>>row_id)&0x1) x=cols-1-col_id;
            else x=col_id;
            if(Scanning[row_id][col_id]) checkBoxs[y][x]->setChecked(true);
            else checkBoxs[y][x]->setChecked(false);
        }
    }
}
void FormMasks::masks_update(void)
{
    //qDebug("[%s--%d] FormMasks ", __func__, __LINE__);
    uint32_t masks[rows];
    uint32_t mask;
    char text[512];
    int len;
    int flag;
    if(scanning) { masks_show(); scanning=0; }
    text[0] = '\0';
    memset(text, 0x00, sizeof(text));
    memset(masks, 0x00, sizeof(masks));
    //qDebug("\r\n[%s--%d] ", __func__, __LINE__);
    for(uint8_t row_id=0; row_id<rows; row_id++)
    {
        mask = 0;
        for(uint8_t col_id=0; col_id<cols; col_id++)
        {
            if((NULL!=checkBoxs[row_id][col_id]) && (checkBoxs[row_id][col_id]->isChecked())) mask |= (0x1<<col_id);
            //if(  (true==checkBoxs[row_id][col_id]->isChecked())) mask |= (0x1<<col_id);
            //checkBoxs[row_id+1][col_id]->setChecked(checkBoxs[row_id][col_id]->isChecked());
        }
        masks[row_id] = mask;
    }
    flag=0;
    for(uint8_t row_id=0; row_id<rows; row_id++)
    {
        if(masks[row_id]!=ctrl.Masks[row_id])
        {
            //qDebug("[%s--%d] match ", __func__, __LINE__);
            flag = 1;
        }
        ctrl.Masks[row_id] = masks[row_id];
    }
    if(flag)
    {
        for(uint8_t row_id=0; row_id<rows; row_id++)
        {
            mask = masks[row_id];
            len = strlen(text);
            snprintf(&text[len], sizeof(text)-1-len, "0x%06X,", mask);
        }
        len = strlen(text);
        text[len-1] = '\0';
        text[sizeof(text)-1] = '\0';
        ui->lineEdit_Mask->setText(QString(text));
        //qDebug("[%s--%d] match text:%s", __func__, __LINE__, text);
    }
    //uint32_t _color = 0x12345678;
    // color: rgb(170, 0, 0);
    //checkBoxs[0][0]->setStyleSheet(QString().asprintf("background-color: rgb(%d, %d, %d);", (_color>>16)&0xFF, (_color>>8)&0xFF, (_color>>0)&0xFF));//设置button背景颜色
    //checkBoxs[0][0]->setStyleSheet(QString().asprintf("color: rgb(%d, %d, %d);", (_color>>16)&0xFF, (_color>>8)&0xFF, (_color>>0)&0xFF));//设置button背景颜色
    //checkBoxs[0][0]->setStyleSheet(QString("QCheckBox{color: blue}"));//设置button背景颜色
}

void FormMasks::masks_show(void)
{
    uint32_t masks[8];
    uint32_t mask;
    //qDebug("[%s--%d] Demo:%d ", __func__, __LINE__, index);
    //qDebug() << ui->comboBox_Demo->currentText();
    kb_map_update(masks, cols, rows, kb104_map);
    for(uint8_t row_id=0; row_id<rows; row_id++)
    {
        mask = masks[row_id];
        for(uint8_t col_id=0; col_id<cols; col_id++)
        {
            if((NULL!=checkBoxs[row_id][col_id]) && ((mask>>col_id)&0x1)) checkBoxs[row_id][col_id]->setChecked(true);
        }
    }
    masks_update();
}

void FormMasks::on_comboBox_Demo_currentIndexChanged(int index)
{
    qDebug("[%s--%d] Demo:%d ", __func__, __LINE__, index);
    qDebug() << ui->comboBox_Demo->currentText();
    masks_show();
}

void FormMasks::on_comboBox_Dir_currentIndexChanged(int index)
{
    qDebug("[%s--%d] Dir:%d ", __func__, __LINE__, index);
    KB_Scanning();
}

void FormMasks::on_comboBox_Start_currentIndexChanged(int index)
{
    qDebug("[%s--%d] Start:%d ", __func__, __LINE__, index);
    KB_Scanning();
}

void FormMasks::on_comboBox_Logo_currentIndexChanged(int index)
{
    qDebug("[%s--%d] Logo:%d ", __func__, __LINE__, index);
    if(0==index)
    {
        ui->lineEdit_Logo->setText("IdxLogo=0xFF");
        ctrl.IdxLogo = 0xFF;
    }
    if(1==index)
    {
        ui->lineEdit_Logo->setText("IdxLogo=0xFE");
        ctrl.IdxLogo = 0xFE;
    }
    if(index>1)
    {
        char text[32];
        memset(text, 0x00, sizeof(text));
        snprintf(text, sizeof(text)-1, "IdxLogo=0x%02X", index-2);
        ui->lineEdit_Logo->setText(QString(text));
        ctrl.IdxLogo = index-2;
    }
}

void FormMasks::KB_Scanning(void)
{
    char text[512];
    uint8_t start=0;
    int Dir = ui->comboBox_Dir->currentIndex();
    int Start = ui->comboBox_Start->currentIndex();
    if(0==Dir) { ctrl.Horizontal=1; ZigZag=0; }   // 横向扫描
    if(1==Dir) { ctrl.Horizontal=0; ZigZag=0; }   // 纵向扫描
    if(2==Dir) { ctrl.Horizontal=1; ZigZag=1; }   // 横向之字形
    if(3==Dir) { ctrl.Horizontal=0; ZigZag=1; }   // 纵向之字形
    if(0==Start) { start=KB_LEFT |KB_UP; }   // 左上,RGB0
    if(1==Start) { start=KB_RIGHT|KB_UP; }   // 右上,RGB20
    if(2==Start) { start=KB_LEFT |KB_DOWN; } // 左下,RGB105
    if(3==Start) { start=KB_RIGHT|KB_DOWN; } // 右下,RGB125
    qDebug("[%s--%d] Horizontal:%d ZigZag:%d start:0x%X ", __func__, __LINE__, ctrl.Horizontal, ZigZag, start);
    kb_scanning(start, ctrl.Horizontal, ZigZag, &ctrl.reverseX, &ctrl.reverseY);
    memset(text, 0x00, sizeof(text));
    snprintf(text, sizeof(text)-1, "RevX=0x%08X,", ctrl.reverseX);
    ui->lineEdit_RevX->setText(QString(text));
    memset(text, 0x00, sizeof(text));
    snprintf(text, sizeof(text)-1, "RevY=0x%08X,", ctrl.reverseY);
    ui->lineEdit_RevY->setText(QString(text));
    qDebug("[%s--%d] reverseX:%08X reverseY:%08X ", __func__, __LINE__, ctrl.reverseX, ctrl.reverseY);
}

